#include "stdafx.h"
#include "Point.h"

Point::Point():x(0),y(0),z(0),w(1){}

Point::Point(float x, float y, float z, float w):x(x),y(y),z(z),w(w){}

Point::Point(float *c):x(c[0]),y(c[1]),z(c[2]),w(c[3]){}

Point::Point(Point const& point)
{
	x = point.x;
	y = point.y;
	z = point.z;
	w = point.w;

	normalize();
}

Point::Point(Point p, float t, Vecteur dir)
{
	dir.normalize();

	x = p.x + t*dir.getX();
	y = p.y + t*dir.getY();
	z = p.z + t*dir.getZ();
	w = p.w;

	normalize();
}

Point::~Point(){}

Point& Point::operator=(Point const& point)
{
	x = point.x;
	y = point.y;
	z = point.z;
	w = point.w;

	normalize();

	return *this;
}

float Point::getX()
{
	return x;
}

float Point::getY()
{
	return y;
}

float Point::getZ()
{
	return z;
}

float Point::getW()
{
	return w;
}

void Point::setX(float x1)
{
	x = x1;
}

void Point::setY(float y1)
{
	y = y1;
}

void Point::setZ(float z1)
{
	z = z1;
}

void Point::setW(float w1)
{
	w = w1;
}

void Point::normalize()
{
	if(w)
	{
		x /= w;
		y /= w;
		z /= w;
		w = 1;
	}
}

float Point::distance(Point p)
{
	float distance;
	normalize();
	p.normalize();

	distance = (float)sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y) + (z-p.z)*(z-p.z));
	return distance;
}

Vecteur Point::getVecteur(Point *p)
{
	Vecteur v(p->x-x, p->y-y, p->z-z);

	return v;
}

Point Point::operator*(Matrice *m)
{
	Point p1;

	normalize();

	p1.x = x*m->getData(0,0) + y*m->getData(1,0) + z*m->getData(2,0) + 1*m->getData(3,0);
	p1.y = x*m->getData(0,1) + y*m->getData(1,1) + z*m->getData(2,1) + 1*m->getData(3,1);
	p1.z = x*m->getData(0,2) + y*m->getData(1,2) + z*m->getData(2,2) + 1*m->getData(3,2);
	p1.w = x*m->getData(0,3) + y*m->getData(1,3) + z*m->getData(2,3) + 1*m->getData(3,3);

	p1.normalize();

	return p1;
}

bool Point::operator==(Point p)
{
	normalize();
	p.normalize();

	if(x == p.x && y == p.y && z == p.z)
		return true;
	else
		return false;
}


Point Point::operator+(Point p)
{
	normalize();
	p.normalize();

	x += p.getX();
	y += p.getY();
	z += p.getZ();

	return *this;

}

std::ostream& Point::display(std::ostream &out) 
{
	out<<"("<<x<<","<<y<<","<<z<<","<<w<<")"<<std::endl;
	return out;
}

std::ostream& operator<<(std::ostream &out,Point p)
{
	return p.display(out);
}